package net.lesscoding.web.server;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author eleven
 * @date 2024/10/22 16:42
 * @apiNote
 */
@Slf4j
public class MultiThreadServerTest {

    @Test
    public void multiThreadServerTest() throws IOException {
        Thread.currentThread().setName("boss");
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        Selector boss = Selector.open();
        SelectionKey bossKey = ssc.register(boss, 0, null);
        bossKey.interestOps(SelectionKey.OP_ACCEPT);
        ssc.bind(new InetSocketAddress(8080));
        // 创建固定数量的 worker
        Worker worker = new Worker("worker-0");

        while (boss.select() > 0) {
            Iterator<SelectionKey> iter = boss.selectedKeys().iterator();
            while (iter.hasNext()) {
                SelectionKey key = iter.next();
                iter.remove();
                if (key.isAcceptable()) {
                    SocketChannel sc = ssc.accept();
                    sc.configureBlocking(false);
                    log.debug("connected ... {}", sc.getRemoteAddress());
                    log.debug("before register ... {}", sc.getRemoteAddress());
                    // 重新注册worker的选择器
                    worker.register(sc);
                    log.debug("after register ... {}", sc.getRemoteAddress());
                }
            }
        }
    }

    @Test
    public void multiCoreWorkersTest() throws IOException {
        Thread.currentThread().setName("boss");
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        Selector boss = Selector.open();
        SelectionKey bossKey = ssc.register(boss, 0, null);
        bossKey.interestOps(SelectionKey.OP_ACCEPT);
        ssc.bind(new InetSocketAddress(8080));
        // 创建固定数量的 worker
        Worker[] workers = new Worker[Runtime.getRuntime().availableProcessors()];
        for (int i = 0; i < workers.length; i++) {
            workers[i] = new Worker("worker-" + i);
        }
        AtomicInteger index = new AtomicInteger();
        while (boss.select() > 0) {
            Iterator<SelectionKey> iter = boss.selectedKeys().iterator();
            while (iter.hasNext()) {
                SelectionKey key = iter.next();
                iter.remove();
                if (key.isAcceptable()) {
                    SocketChannel sc = ssc.accept();
                    sc.configureBlocking(false);
                    log.debug("connected ... {}", sc.getRemoteAddress());
                    log.debug("before register ... {}", sc.getRemoteAddress());
                    // 重新注册worker的选择器
                    workers[index.getAndIncrement() % workers.length].register(sc);
                    log.debug("after register ... {}", sc.getRemoteAddress());
                }
            }
        }
    }

    @Test
    public void getCpuCore() {
        System.out.println(Runtime.getRuntime().availableProcessors());
    }

}
